package com.ui.panel;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileSystemView;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

import org.apache.commons.dbutils.ColumnHandler;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import com.ui.AddMetadataColumn;
import com.ui.Application;
import com.ui.bean.ClassVO;
import com.ui.bean.PropertyVO;

import cn.hutool.core.util.StrUtil;
import org.apache.commons.dbutils.handlers.ColumnListHandler;

public class ExtendedPanel extends JPanel implements ActionListener {

    /**
     *
     */
    private static final long serialVersionUID = 1L;
    private Connection conn;
    private JTextField tableNameText, classIDText, filePathText; // 表明，实体ID,文件存储路径
    private JButton browseBtn, okBtn, cancelBtn; // 浏览按钮，生成脚本，推出按钮
    private JTextField serialText, defNameText, beginSerialText, defCountText;
    private Application parentContainer; // 上级组件

    public ExtendedPanel(Application parentContainer, Connection conn) {
        this.conn = conn;
        this.parentContainer = parentContainer;
        initUI();
    }

    /**
     * 初始化UI
     */
    public void initUI() {
        this.setLayout(new BorderLayout());
        this.add(getUpPanel(), BorderLayout.NORTH);
        this.add(getLogPanel());
        this.add(getBtnPanel(), BorderLayout.SOUTH);
    }

    /**
     * 日志面板
     *
     * @return
     */
    private JPanel getLogPanel() {
        JPanel upPanel = new JPanel();
        TitledBorder titledBorder = BorderFactory.createTitledBorder("日志信息");
        titledBorder.setTitleJustification(TitledBorder.LEFT);
        upPanel.setBorder(titledBorder);
        upPanel.add(getLogArea());
        return upPanel;
    }

    /**
     * 按钮面板
     *
     * @return
     */
    private JPanel getBtnPanel() {
        JPanel btnPanel = new JPanel();
        btnPanel.add(getOkBtn());
        btnPanel.add(getCancelBtn());
        return btnPanel;
    }

    /**
     * 主要信息面板
     *
     * @return
     */
    private JPanel getUpPanel() {
        JPanel upPanel = new JPanel();
        TitledBorder titledBorder = BorderFactory.createTitledBorder("实体信息");
        titledBorder.setTitleJustification(TitledBorder.LEFT);
        upPanel.setLayout(new BorderLayout());
        upPanel.setBorder(titledBorder);
        upPanel.add(getInfoPanel(), BorderLayout.NORTH);
        upPanel.add(getFilePanel(), BorderLayout.SOUTH);
        upPanel.add(getDefPanel());
        return upPanel;
    }

    /**
     * 实体信息面板
     *
     * @return
     */
    private JPanel getInfoPanel() {
        JPanel infoPanel = new JPanel();
        infoPanel.add(new JLabel("ClassID:"));
        infoPanel.add(getClassIDText());
        infoPanel.add(new JLabel("表名:"));
        infoPanel.add(getTableNameText());
        infoPanel.add(new JLabel("起始序号:"));
        infoPanel.add(getSerialText());
        return infoPanel;
    }

    /**
     * 表名文本框
     *
     * @return
     */
    private JTextField getTableNameText() {
        if (tableNameText == null) {
            tableNameText = new JTextField(10);
        }
        return tableNameText;
    }

    private void connect() {
        try {
            logger("开始连接数据库...");
            if (conn != null && !conn.isClosed()) {
                conn.close();
            }
            String url = parentContainer.getHostText().getText();
            String uname = parentContainer.getUserText().getText();
            String pwd = parentContainer.getPwdText().getText();
            if (StrUtil.isNotEmpty(url) && StrUtil.isNotEmpty(uname) && StrUtil.isNotEmpty(pwd)) {
                DbUtils.loadDriver("oracle.jdbc.driver.OracleDriver");
                conn = DriverManager.getConnection(url, uname, pwd);
                logger("连接数据库成功...");
            } else {
                logger("数据库信息不完整不尝试连接...");
            }

        } catch (Exception e) {
            logger("连接数据库失败：" + e);
//			JOptionPane.showMessageDialog(addLineBtn,"连接数据库失败：" + e, "错误", 0);
        }
    }

    /**
     * 实体ID文本框
     *
     * @return
     */
    private JTextField getClassIDText() {
        if (classIDText == null) {
            classIDText = new JTextField(25);
            classIDText.addKeyListener(new KeyListener() {

                @Override
                public void keyTyped(KeyEvent e) {

                }

                @Override
                public void keyReleased(KeyEvent e) {

                }

                @Override
                public void keyPressed(KeyEvent e) {
                    if (e.getKeyChar() == KeyEvent.VK_ENTER) {
                        parentContainer.getLogText().requestFocus();
                    }
                }
            });
            classIDText.addFocusListener(new FocusListener() {

                @Override
                public void focusLost(FocusEvent e) {
                    try {
                        String classID = getClassIDText().getText();
                        if (conn == null || conn.isClosed()) {
                            connect();
                        }
                        if (conn != null && !conn.isClosed() && !StrUtil.isEmpty(classID)) {
                            QueryRunner queryRunner = new QueryRunner();
                            ResultSetHandler<ClassVO> resultHandler = new BeanHandler<ClassVO>(ClassVO.class);
                            ClassVO classVO = queryRunner.query(conn,
                                    "select * from md_class where id = '" + classID + "'", resultHandler);
                            if (classVO != null) {
                                logger("获取到实体：" + classVO.getDisplayName());
                                String tableName = classVO.getDefaultTableName();
                                getTableNameText().setText(tableName);
                                ResultSetHandler<List<PropertyVO>> resultHandler2 = new BeanListHandler<PropertyVO>(
                                        PropertyVO.class);
                                List<PropertyVO> propertyVOs = queryRunner.query(conn,
                                        "select * from md_property where classid = '" + classID + "'", resultHandler2);
                                List<BigDecimal> maxAttrsequence = queryRunner.query(conn,
                                        "select max(ATTRSEQUENCE) from md_property where classid = '" + classID + "' group by CLASSID", new ColumnListHandler<BigDecimal>());
                                List<BigDecimal> maxDefNum = queryRunner.query(conn,
                                        "select count(distinct name)+1  from md_property where classid = '" + classID + "' and DATATYPE = 'BS000010000100001056'", new ColumnListHandler<BigDecimal>());
                                if (propertyVOs != null && !propertyVOs.isEmpty()) {
                                    getSerialText().setText(maxAttrsequence.get(0).toString());
                                    int defNum = 1;
                                    String defName = "";
                                    for (PropertyVO iAttribute : propertyVOs) {
                                        if ("BS000010000100001056".equals(iAttribute.getDataType())) { // 自定义项
                                            // BS000010000100001056
                                            defNum++;
                                            defName = iAttribute.getName();
                                        }
                                    }
                                    String prefix = "def";

                                    if (!StrUtil.isEmpty(defName)) {
                                        String[] part = defName.split("(?<=\\D)(?=\\d)");
                                        prefix = part[0];
                                    }

                                    getDefNameText().setText(prefix);
                                    getDefCountText().setText("20");
                                    getBeginSerialText().setText(String.valueOf(maxDefNum.get(0)));
                                } else {
                                    logger("没有查到实体属性...");
                                }
                            } else {
                                logger("没有查到实体类...");
                            }
                        } else {
                            logger("连接数据库失败，不根据数据库处理...");
                        }

                    } catch (Exception e1) {
                        JOptionPane.showMessageDialog(null, e1, "错误", 0);
                    }

                }

                @Override
                public void focusGained(FocusEvent e) {
                    // TODO Auto-generated method stub

                }
            });
        }
        return classIDText;
    }

    /**
     * 路径文本框
     *
     * @return
     */
    private JTextField getFilePathText() {
        if (filePathText == null) {
            filePathText = new JTextField(43);
        }
        return filePathText;
    }

    /**
     * 选择路径按钮
     *
     * @return
     */
    private JButton getBrowseBtn() {
        if (browseBtn == null) {
            browseBtn = new JButton("浏览");
            browseBtn.addActionListener(this);
        }
        return browseBtn;
    }

    /**
     * 生成脚本按钮
     *
     * @return
     */
    private JButton getOkBtn() {
        if (okBtn == null) {
            okBtn = new JButton("生成脚本");
            okBtn.addActionListener(this);
        }
        return okBtn;
    }

    /**
     * 推出按钮
     *
     * @return
     */
    private JButton getCancelBtn() {
        if (cancelBtn == null) {
            cancelBtn = new JButton("退出");
            cancelBtn.addActionListener(this);
        }
        return cancelBtn;
    }

    /**
     * 自定义名框
     *
     * @return
     */
    private JTextField getDefNameText() {
        if (defNameText == null) {
            defNameText = new JTextField(8);
        }
        return defNameText;
    }

    /**
     * 自定义项开始序号
     *
     * @return
     */
    private JTextField getBeginSerialText() {
        if (beginSerialText == null) {
            beginSerialText = new JTextField(6);
            beginSerialText.setDocument(new NumberTextField());
        }
        return beginSerialText;
    }

    /**
     * 自定义项个数框
     *
     * @return
     */
    private JTextField getDefCountText() {
        if (defCountText == null) {
            defCountText = new JTextField(6);
            defCountText.setDocument(new NumberTextField());
        }
        return defCountText;
    }

    /**
     * 实体已有字段框
     *
     * @return
     */
    private JTextField getSerialText() {
        if (serialText == null) {
            serialText = new JTextField(5);
            serialText.setDocument(new NumberTextField());
        }
        return serialText;
    }

    /**
     * 日志域
     *
     * @return
     */
    private JScrollPane getLogArea() {
        return new JScrollPane(this.parentContainer.getLogText());
    }

    /**
     * 自定义项信息面板
     *
     * @return
     */
    private JPanel getDefPanel() {
        JPanel defPanel = new JPanel();
        defPanel.add(new JLabel("自定义项字段名称:"));
        defPanel.add(getDefNameText());
        defPanel.add(new JLabel("自定义项起始值:"));
        defPanel.add(getBeginSerialText());
        defPanel.add(new JLabel("自定义项数量:"));
        defPanel.add(getDefCountText());
        return defPanel;
    }

    /**
     * 存储文件区域面板
     *
     * @return
     */
    private JPanel getFilePanel() {
        JPanel filePanel = new JPanel();
        filePanel.add(getFilePathText());
        filePanel.add(getBrowseBtn());
        return filePanel;
    }

    /**
     * 记录日志
     *
     * @param message
     */
    private void logger(String message) {
        parentContainer.getLogText().append(message);
        parentContainer.getLogText().append(System.lineSeparator());
        parentContainer.getLogText().setCaretPosition(parentContainer.getLogText().getText().length());
    }

    /**
     * 按钮事件
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == this.browseBtn) {
            JFileChooser fileChooser = new JFileChooser();
            FileSystemView fileSystemView = FileSystemView.getFileSystemView();
            fileChooser.setCurrentDirectory(fileSystemView.getHomeDirectory());
            fileChooser.setDialogTitle("保存路径");
            fileChooser.setApproveButtonText("选择文件夹");
            fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            int rs = fileChooser.showOpenDialog(this);
            if (rs == JFileChooser.APPROVE_OPTION) {
                this.filePathText.setText(fileChooser.getSelectedFile().getPath());
            }
        } else if (e.getSource() == this.cancelBtn) {
            this.parentContainer.dispose();
        } else if (e.getSource() == this.okBtn) {
            String tableName = this.getTableNameText().getText();
            String classID = this.getClassIDText().getText();
            String serial = this.getSerialText().getText();
            String defName = this.getDefNameText().getText();
            String beginSerial = this.getBeginSerialText().getText();
            String defCount = this.getDefCountText().getText();
            if (tableName == null || tableName.equals("") || classID == null || classID.equals("") || serial == null
                    || serial.equals("")) {
                JOptionPane.showMessageDialog(this, "表名和ClassID以及起始序号都不能为空不能为空");
                return;
            }
            if (defName == null || defName.equals("") || beginSerial == null || beginSerial.equals("")
                    || defCount == null || defCount.equals("")) {
                int rs = JOptionPane.showConfirmDialog(null, "自定义项字段名称为空值，是否赋予字段名为vdef？");
                if (rs == 0)
                    defName = "vdef";
                else
                    return;
            }
            if (defName == null || defName.equals("") || beginSerial == null || beginSerial.equals("")
                    || defCount == null || defCount.equals("")) {
                JOptionPane.showMessageDialog(this, "自定义项数量不能为空!!!!");
                return;
            }
            if (defName == null || defName.equals("") || beginSerial == null || beginSerial.equals("")
                    || defCount == null || defCount.equals("")) {
                int rs = JOptionPane.showConfirmDialog(null, "自定义项起始值为空，是否采用默认自定义项字段名为vdef00，起始值为01？");
                if (rs == 0) {
                    defName = "vdef";
                    beginSerial = "01";
                } else
                    return;
            }
            String path = this.getFilePathText().getText();
            if (path == null || path.equals("")) {
                int rs = JOptionPane.showConfirmDialog(null, "路径为空是否保存到桌面");
                if (rs == 0)
                    path = FileSystemView.getFileSystemView().getHomeDirectory().getPath();
                else
                    return;
            }
            logger("开始生成脚本....");
            AddMetadataColumn addMetadataColumn = new AddMetadataColumn(tableName, classID, Integer.parseInt(defCount),
                    Integer.parseInt(serial), Integer.parseInt(beginSerial), defName);
            addMetadataColumn.generateScript();
            StringBuffer buffer = addMetadataColumn.getIsnertScript();
            StringBuffer delsql = addMetadataColumn.getDelScript();
            StringBuffer addCloumnScript = addMetadataColumn.getAddCloumnScript();
            StringBuffer dropCloumnScript = addMetadataColumn.getDropCloumnScript();
            StringBuffer xmlBf = addMetadataColumn.getScriptXML();
            StringBuffer javaBf1 = addMetadataColumn.getJavaKey();
            StringBuffer javaBf2 = addMetadataColumn.getJavaKey2();
            logger("开始insert脚本....");
            logger(buffer.toString());
            logger("开始加表字段脚本....");
            logger(addCloumnScript.toString());
            logger("开始生成delete脚本....");
            logger(delsql.toString());
            logger("开始生成删表字段脚本....");
            logger(dropCloumnScript.toString());
            logger("开始生成java字段类型1代码....");
            logger(javaBf1.toString());
            logger("开始生成java字段类型2代码....");
            logger(javaBf2.toString());
            logger("开始生成元数据xml列....");
            logger(xmlBf.toString());
            OutputStream out = null;
            logger("开始保存....");
            try {
                File dir = new File(path + "/" + tableName);
                if (!dir.exists()) {
                    dir.mkdir();
                }
                out = new FileOutputStream(path + "/" + tableName + "/" + tableName + ".sql");
                out.write(buffer.toString().getBytes());
                out.close();

                out = new FileOutputStream(path + "/" + tableName + "/" + tableName + "_addcolumn.sql");
                out.write(addCloumnScript.toString().getBytes());
                out.close();

                out = new FileOutputStream(path + "/" + tableName + "/" + tableName + "_delete.sql");
                out.write(delsql.toString().getBytes());
                out.close();

                out = new FileOutputStream(path + "/" + tableName + "/" + tableName + "_dropcolumn.sql");
                out.write(dropCloumnScript.toString().getBytes());
                out.close();

                out = new FileOutputStream(path + "/" + tableName + "/" + tableName + "_metadata.xml");
                out.write(xmlBf.toString().getBytes());
                out.close();

                out = new FileOutputStream(path + "/" + tableName + "/" + tableName + "_vo1.java");
                out.write(javaBf1.toString().getBytes());
                out.close();

                out = new FileOutputStream(path + "/" + tableName + "/" + tableName + "_vo2.java");
                out.write(javaBf2.toString().getBytes());
                out.close();
                logger("处理完毕....");
            } catch (Exception e1) {
                logger("处理异常...." + e1);
            }

        }
    }

    class NumberTextField extends PlainDocument {
        /**
         *
         */
        private static final long serialVersionUID = 1L;

        public NumberTextField() {
            super();
        }

        @Override
        public void insertString(int offset, String str, javax.swing.text.AttributeSet attr)
                throws BadLocationException {
            if (str == null) {
                return;
            }

            char[] s = str.toCharArray();
            int length = 0;
            // 过滤非数字
            for (int i = 0; i < s.length; i++) {
                if ((s[i] >= '0') && (s[i] <= '9')) {
                    s[length++] = s[i];
                }
            }
            super.insertString(offset, new String(s, 0, length), attr);
        }
    }

}
